PHP 递归函数的应用(一) 数组的无限级分类和逆过程

递归函数最基本的特点就是自身调用自身,在调用自身前有条件判断,否则会无限调用下去。在日常开发也会很常见,对逻辑性要求也较高,要想灵活的去运用,还需要多加尝试,利用递归,可以对数组进行无限极的分类,还可以对无限极分类的数组进行还原。

先看看无限极分类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
$data = array(
0 => array('id' => '1', 'pid' => 0, 'name' => '一级栏目一'),
1 => array('id' => '2', 'pid' => 1, 'name' => '二级栏目一'),
2 => array('id' => '3', 'pid' => 1, 'name' => '二级栏目二'),
3 => array('id' => '4', 'pid' => 2, 'name' => '三级栏目一'),
4 => array('id' => '5', 'pid' => 2, 'name' => '三级栏目二'),
5 => array('id' => '6', 'pid' => 3, 'name' => '三级栏目三'),
6 => array('id' => '7', 'pid' => 3, 'name' => '三级栏目四'),
7 => array('id' => '8', 'pid' => 0, 'name' => '一级栏目二'),
8 => array('id' => '9', 'pid' => 8, 'name' => '二级栏目三'),
9 => array('id' => '10', 'pid' => 7, 'name' => '四级栏目一')
);


//无限极分类
function assortArray($data, $pid = 0)
{
$r = array();
foreach ($list as $id => $item) {
if ($item['pid'] == $pid) {
$length = count($r);
$r[$length] = $item;
if ($t = assortArray($list, $item['id'])) {
$r[$length]['children'] = $t;
}
}
}
return $r;
}

//还原
function arrRecove($array)
{
static $r = [];
if (is_array($array) && count($array) > 0) {
foreach ($array as $k => $v) {
$r[] = array(
'id' => $v['id'],
'pid' => $v['pid'],
'name' => $v['name']
);
if (isset($v['children'])) {
arrRecove($v['children']);
}
}
}
return $r;
}

调用以后输出,可以看到结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
array(2) {
[0]=>
array(4) {
["id"]=>
string(1) "1"
["pid"]=>
int(0)
["name"]=>
string(15) "一级栏目一"
["children"]=>
array(2) {
[0]=>
array(4) {
["id"]=>
string(1) "2"
["pid"]=>
int(1)
["name"]=>
string(15) "二级栏目一"
["children"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(1) "4"
["pid"]=>
int(2)
["name"]=>
string(15) "三级栏目一"
}
[1]=>
array(3) {
["id"]=>
string(1) "5"
["pid"]=>
int(2)
["name"]=>
string(15) "三级栏目二"
}
}
}
[1]=>
array(4) {
["id"]=>
string(1) "3"
["pid"]=>
int(1)
["name"]=>
string(15) "二级栏目二"
["children"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
string(1) "6"
["pid"]=>
int(3)
["name"]=>
string(15) "三级栏目三"
}
[1]=>
array(4) {
["id"]=>
string(1) "7"
["pid"]=>
int(3)
["name"]=>
string(15) "三级栏目四"
["children"]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(2) "10"
["pid"]=>
int(7)
["name"]=>
string(15) "四级栏目一"
}
}
}
}
}
}
}
[1]=>
array(4) {
["id"]=>
string(1) "8"
["pid"]=>
int(0)
["name"]=>
string(15) "一级栏目二"
["children"]=>
array(1) {
[0]=>
array(3) {
["id"]=>
string(1) "9"
["pid"]=>
int(8)
["name"]=>
string(15) "二级栏目三"
}
}
}
}

可以看到最外层的数组只有我们的一级栏目,然后子栏目都嵌套在其中

运行arrRecove()方法,即可把数组还原到二维数组

甚至可以用一种更简单粗暴的分级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//无限极分类
function assortArray($data, $pid = 0)
{
$r = array();
foreach ($list as $id => $item) {
if ($item['pid'] == $pid) {
if ($t = assortArray($list, $item['id'])) {
$r[$item['name']] = $t;
} else {
$r[] = $item['name'];
}
}
}
return $r;
}

//还原
function arrshift($array, $pid = 0)
{
static $r = [];
static $index = 1;
if (is_array($array) && count($array) > 0) {
foreach ($array as $k => $v) {
$r[] = array(
'id' => $index,
'pid' => $pid,
'name' => is_array($v) ? $k : $v
);
$index++;
arrshift($v, $index - 1);
}
}
return $r;
}

运行分级方法可以看到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
array(2) {
["一级栏目一"]=>
array(2) {
["二级栏目一"]=>
array(2) {
[0]=>
string(15) "三级栏目一"
[1]=>
string(15) "三级栏目二"
}
["二级栏目二"]=>
array(2) {
[0]=>
string(15) "三级栏目三"
["三级栏目四"]=>
array(1) {
[0]=>
string(15) "四级栏目一"
}
}
}
["一级栏目二"]=>
array(1) {
[0]=>
string(15) "二级栏目三"
}
}

运行arrRecove()方法,同样可以把数组还原到二维数组

不同的分级方式,还原的方法也就不一样